package com.firsteapps.mobile.android.puzzle;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.text.Html;
import android.text.SpannableStringBuilder;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;

import com.firsteapps.mobile.android.puzzle.BillingService.RequestPurchase;
import com.firsteapps.mobile.android.puzzle.BillingService.RestoreTransactions;
import com.firsteapps.mobile.android.puzzle.game.Helper;
import com.firsteapps.mobile.android.puzzle.util.Consts;
import com.firsteapps.mobile.android.puzzle.util.Consts.PurchaseState;
import com.firsteapps.mobile.android.puzzle.util.Consts.ResponseCode;

public class ShopHere extends PostLoginBase {

	private static final String TAG = "Purchase";

	private ImageView buySelectedAmmount;
	private RadioGroup buyCredits;
	private TextView credits_5, credits_10, credits_15, credits_20;
	private RadioButton buy_credits_5, buy_credits_10, buy_credits_15, buy_credits_20;

	private CreditPurchaseObserver mPurchaseObserver;
	private Handler mHandler;

	private BillingService mBillingService;
	// private TextView mLogTextView;
	// private PurchaseDatabase mPurchaseDatabase;

	private static final int DIALOG_CANNOT_CONNECT_ID = 1;
	private static final int DIALOG_BILLING_NOT_SUPPORTED_ID = 2;

	/**
	 * Each product in the catalog is either MANAGED or UNMANAGED. MANAGED means that the product can be purchased only
	 * once per user (such as a new level in a game). The purchase is remembered by Android Market and can be restored
	 * if this application is uninstalled and then re-installed. UNMANAGED is used for products that can be used up and
	 * purchased multiple times (such as poker chips). It is up to the application to keep track of UNMANAGED products
	 * for the user.
	 */
	private enum Managed {
		MANAGED, UNMANAGED
	}

	/**
	 * A {@link PurchaseObserver} is used to get callbacks when Android Market sends messages to this application so
	 * that we can update the UI.
	 */
	private class CreditPurchaseObserver extends PurchaseObserver {
		public CreditPurchaseObserver(Handler handler) {
			super(ShopHere.this, handler);
		}

		@Override
		public void onBillingSupported(boolean supported) {
			if (Consts.DEBUG) {
				Log.i(TAG, "supported: " + supported);
			}
			if (!supported) {
				showDialog(DIALOG_BILLING_NOT_SUPPORTED_ID);
			}
		}

		@Override
		public void onPurchaseStateChange(PurchaseState purchaseState, String itemId, int quantity, long purchaseTime,
				String developerPayload) {
			if (Consts.DEBUG) {
				Log.i(TAG, "onPurchaseStateChange() itemId: " + itemId + " " + purchaseState);
			}

			if (developerPayload == null) {
				logProductActivity(itemId, purchaseState.toString());
			}

			if (purchaseState == PurchaseState.PURCHASED) {
				if (Helper.updateAccountBalance(ShopHere.this, Consts.FILE_NAME_ACCOUNT_BALANCE, getPurchasedItem(itemId)))
					Helper.doMessageDialog(ShopHere.this, "Buy Credits", "You have successfully purchased the credits");
			}
			// mCatalogAdapter.setOwnedItems(mOwnedItems);
			// mOwnedItemsCursor.requery();
		}

		@Override
		public void onRequestPurchaseResponse(RequestPurchase request, ResponseCode responseCode) {
			if (Consts.DEBUG) {
				Log.d(TAG, request.mProductId + ": " + responseCode);
			}
			if (responseCode == ResponseCode.RESULT_OK) {
				if (Consts.DEBUG) {
					Log.i(TAG, "purchase was successfully sent to server");
				}
				logProductActivity(request.mProductId, "sending purchase request");
			} else if (responseCode == ResponseCode.RESULT_USER_CANCELED) {
				if (Consts.DEBUG) {
					Log.i(TAG, "user canceled purchase");
				}
				logProductActivity(request.mProductId, "dismissed purchase dialog");
			} else {
				if (Consts.DEBUG) {
					Log.i(TAG, "purchase failed");
				}
				logProductActivity(request.mProductId, "request purchase returned " + responseCode);
			}
		}

		@Override
		public void onRestoreTransactionsResponse(RestoreTransactions request, ResponseCode responseCode) {
			if (responseCode == ResponseCode.RESULT_OK) {
				if (Consts.DEBUG) {
					Log.d(TAG, "completed RestoreTransactions request");
				}
			} else {
				if (Consts.DEBUG) {
					Log.d(TAG, "RestoreTransactions error: " + responseCode);
				}
			}
		}
	}

	private static class CatalogEntry {
		public String sku;
		public int nameId;
		public Managed managed;

		public CatalogEntry(String sku, int nameId, Managed managed) {
			this.sku = sku;
			this.nameId = nameId;
			this.managed = managed;
		}
	}

	/** An array of product list entries for the products that can be purchased. */
	private static final CatalogEntry[] CATALOG = new CatalogEntry[] {
			// new CatalogEntry("android.test.purchased", R.string.android_test_purchased, Managed.UNMANAGED),
			// new CatalogEntry("android.test.canceled", R.string.android_test_canceled, Managed.UNMANAGED),
			// new CatalogEntry("android.test.refunded", R.string.android_test_refunded, Managed.UNMANAGED),
			// new CatalogEntry("android.test.item_unavailable", R.string.android_test_item_unavailable,
			// Managed.UNMANAGED),
			new CatalogEntry("credit_5", R.string.credit_5, Managed.UNMANAGED),
			new CatalogEntry("credit_10", R.string.credit_10, Managed.UNMANAGED),
			new CatalogEntry("credit_15", R.string.credit_15, Managed.UNMANAGED),
			new CatalogEntry("credit_20", R.string.credit_20, Managed.UNMANAGED) };

	private String mItemName;
	private String mSku;

	private int getPurchasedItem(String itemId) {
		for (int i = 0; i < CATALOG.length; i++) {
			if (itemId.equals(CATALOG[i].sku)) {
				return 5 * (i + 1);
			}
		}
		return 0;
	}

	// private CatalogAdapter mCatalogAdapter;

	/**
	 * Called when this activity becomes visible.
	 */
	@Override
	protected void onStart() {
		super.onStart();
		ResponseHandler.register(mPurchaseObserver);
	}

	/**
	 * Called when this activity is no longer visible.
	 */
	@Override
	protected void onStop() {
		super.onStop();
		ResponseHandler.unregister(mPurchaseObserver);
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		// mPurchaseDatabase.close();
		mBillingService.unbind();
	}

	/**
	 * Save the context of the log so simple things like rotation will not result in the log being cleared.
	 */
	@Override
	protected void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		// outState.putString(LOG_TEXT_KEY, Html.toHtml((Spanned)
		// mLogTextView.getText()));
	}

	/**
	 * Restore the contents of the log if it has previously been saved.
	 */
	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState) {
		super.onRestoreInstanceState(savedInstanceState);
		if (savedInstanceState != null) {
			// mLogTextView.setText(Html.fromHtml(savedInstanceState.getString(LOG_TEXT_KEY)));
		}
	}

	@Override
	protected Dialog onCreateDialog(int id) {
		switch (id) {
		case DIALOG_CANNOT_CONNECT_ID:
			return createDialog(R.string.cannot_connect_title, R.string.cannot_connect_message);
		case DIALOG_BILLING_NOT_SUPPORTED_ID:
			return createDialog(R.string.billing_not_supported_title, R.string.billing_not_supported_message);
		default:
			return null;
		}
	}

	private Dialog createDialog(int titleId, int messageId) {
		String helpUrl = getString(R.string.help_url);
		if (Consts.DEBUG) {
			Log.i(TAG, helpUrl);
		}
		final Uri helpUri = Uri.parse(helpUrl);

		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle(titleId).setIcon(android.R.drawable.stat_sys_warning).setMessage(messageId).setCancelable(false)
				.setPositiveButton(android.R.string.ok, null)
				.setNegativeButton(R.string.learn_more, new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						Intent intent = new Intent(Intent.ACTION_VIEW, helpUri);
						startActivity(intent);
					}
				});
		return builder.create();
	}

	/**
	 * Sets up the UI.
	 */
	private void setupWidgets() {
		// mLogTextView = (TextView) findViewById(R.id.log);

		// mSelectItemSpinner = (Spinner) findViewById(R.id.item_choices);
		// mCatalogAdapter = new CatalogAdapter(this, CATALOG);
		// mSelectItemSpinner.setAdapter(mCatalogAdapter);
		// mSelectItemSpinner.setOnItemSelectedListener(this);

	}

	private void prependLogEntry(CharSequence cs) {
		SpannableStringBuilder contents = new SpannableStringBuilder(cs);
		contents.append('\n');
		// contents.append(mLogTextView.getText());
		// mLogTextView.setText(contents);
		System.out.println(contents);
	}

	private void logProductActivity(String product, String activity) {
		SpannableStringBuilder contents = new SpannableStringBuilder();
		contents.append(Html.fromHtml("<b>" + product + "</b>: "));
		contents.append(activity);
		prependLogEntry(contents);
	}

	public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
		mItemName = getString(CATALOG[position].nameId);
		mSku = CATALOG[position].sku;
	}

	public void onNothingSelected(AdapterView<?> arg0) {
	}

	// /**
	// * An adapter used for displaying a catalog of products. If a product is
	// * managed by Android Market and already purchased, then it will be
	// * "grayed-out" in the list and not selectable.
	// */
	// private static class CatalogAdapter extends ArrayAdapter<String> {
	// private CatalogEntry[] mCatalog;
	// private Set<String> mOwnedItems = new HashSet<String>();
	//
	// public CatalogAdapter(Context context, CatalogEntry[] catalog) {
	// super(context, android.R.layout.simple_spinner_item);
	// mCatalog = catalog;
	// for (CatalogEntry element : catalog) {
	// add(context.getString(element.nameId));
	// }
	// setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
	// }
	//
	// public void setOwnedItems(Set<String> ownedItems) {
	// mOwnedItems = ownedItems;
	// notifyDataSetChanged();
	// }
	//
	// @Override
	// public boolean areAllItemsEnabled() {
	// // Return false to have the adapter call isEnabled()
	// return false;
	// }
	//
	// @Override
	// public boolean isEnabled(int position) {
	// // If the item at the given list position is not purchasable,
	// // then prevent the list item from being selected.
	// CatalogEntry entry = mCatalog[position];
	// if (entry.managed == Managed.MANAGED && mOwnedItems.contains(entry.sku)) {
	// return false;
	// }
	// return true;
	// }
	//
	// @Override
	// public View getDropDownView(int position, View convertView, ViewGroup parent) {
	// // If the item at the given list position is not purchasable, then
	// // "gray out" the list item.
	// View view = super.getDropDownView(position, convertView, parent);
	// view.setEnabled(isEnabled(position));
	// return view;
	// }
	// }

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.buy_credits);

		mHandler = new Handler();
		mPurchaseObserver = new CreditPurchaseObserver(mHandler);
		mBillingService = new BillingService();
		mBillingService.setContext(this);

		// mPurchaseDatabase = new PurchaseDatabase(this);
		// setupWidgets();

		// Check if billing is supported.
		ResponseHandler.register(mPurchaseObserver);
		if (!mBillingService.checkBillingSupported()) {
			showDialog(DIALOG_CANNOT_CONNECT_ID);
		}

		buySelectedAmmount = (ImageView) findViewById(R.id.buy_selected_amount);
		buyCredits = (RadioGroup) findViewById(R.id.rg_buy_credits);

		credits_5 = (TextView) findViewById(R.id.buy_5);
		credits_10 = (TextView) findViewById(R.id.buy_10);
		credits_15 = (TextView) findViewById(R.id.buy_15);
		credits_20 = (TextView) findViewById(R.id.buy_20);

		buy_credits_5 = (RadioButton) buyCredits.findViewById(R.id.bc_5credits);
		buy_credits_10 = (RadioButton) buyCredits.findViewById(R.id.bc_10credits);
		buy_credits_15 = (RadioButton) buyCredits.findViewById(R.id.bc_15credits);
		buy_credits_20 = (RadioButton) buyCredits.findViewById(R.id.bc_20credits);

		buySelectedAmmount.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				final int id = buyCredits.getCheckedRadioButtonId();
				final int position = getSelectedAmount();
				if (id != -1 && position >= 0) {
					Helper.doMessageDialog(ShopHere.this, "Buy Credits", "Are you sure you want to buy the credits?",
							new DialogInterface.OnClickListener() {
								@Override
								public void onClick(DialogInterface dialog, int which) {
									System.out.println(position);

									mItemName = getString(CATALOG[position].nameId);
									mSku = CATALOG[position].sku;

									if (Consts.DEBUG) {
										Log.d(TAG, "buying: " + mItemName + " sku: " + mSku);
									}
									if (!mBillingService.requestPurchase(mSku, null)) {
										showDialog(DIALOG_BILLING_NOT_SUPPORTED_ID);
									}
								}
							}, true);
				} else
					Helper.doMessageDialog(ShopHere.this, "Buy Credits", "Credit amount is not selected");
			}
		});

		credits_5.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				buyCredits.clearCheck();
				buy_credits_5.setChecked(true);
			}
		});

		credits_10.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				buyCredits.clearCheck();
				buy_credits_10.setChecked(true);
			}
		});

		credits_15.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				buyCredits.clearCheck();
				buy_credits_15.setChecked(true);
			}
		});

		credits_20.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				buyCredits.clearCheck();
				buy_credits_20.setChecked(true);
			}
		});
	}

	private int getSelectedAmount() {
		if (buy_credits_5.isChecked())
			return 0;
		if (buy_credits_10.isChecked())
			return 1;
		if (buy_credits_15.isChecked())
			return 2;
		if (buy_credits_20.isChecked())
			return 3;
		return -1;
	}
}
